---
title: useTextField
description: The useTextField hook can be used for extremely simple validation using the browser's constraint validation. If values need to be validate with complex logic or against other fields, use react-hook-form or another library instead.
docType: Demo
docGroup: Hooks
group: Form State
hooks: [useTextField]
components: [TextField]
---

# useTextField [$SOURCE](packages/core/src/form/useTextField.ts)

```ts disableTransform
function useTextField<E extends HTMLInputElement | HTMLTextAreaElement>(
  options: TextFieldHookOptions<E>
): ValidatedTextFieldImplementation<E>;
```

The `useTextField` hook can be used for extremely simple validation using the
[browser's constraint validation](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5/Constraint_validation).
If values need to be validate with complex logic or against other fields, use
[react-hook-form](https://react-hook-form.com/) or another library instead.

## Example Usage

The main purpose of this hook is to help validate the value using constraint
validation. Use the `required`, `pattern`, `minLength`, and `maxLength` options
to start getting real time validation once the field is blurred or the form is
submitted.

```demo source="./AddingConstraintsExample.tsx"

```

### Custom Validation

Custom error messaging can be provided using the `getErrorMessage` option. It
should return a string

```demo source="./CustomValidationExample.tsx"

```

### Additional Return Values

The `useTextField` hook returns some other values and functions to customize or
control the text field behavior.

```tsx
function Example() {
  const { value, error, errorMessage, reset, setState, fieldRef, fieldProps } =
    useTextField({
      name: "example",
    });

  return <TextField label="Field" {...fieldProps} />;
}
```

### Inline Counter

An inline counter can be displayed be enabling the `counter` option along with
the `maxLength` option. If the user should be able to insert text beyond the
max length limit, enable the `disableMaxLength` option as well to prevent
passing the `maxLength` option to the `<input>`>

```demo source="./InlineCounterExample.tsx"

```

### Validation Type

This validation timing can be customized by providing the `validationType`
option which can be one of:

- `"recommended"` (default) - validate when the `"badInput"`, `"tooLong"`, or `"valueMissing"`
  error occurs as the user types. otherwise display any errors once the input is blurred
- `"blur"` - only validate on blur
- `"change"` - validate on each keystroke
- One or many of the [ValidityState input options](https://developer.mozilla.org/en-US/docs/Web/API/ValidityState#instance_properties)
  - i.e. `"valueMissing"` or `["badInput", "customError", "tooLong"]`

```demo source="./ValidationTypeExample.tsx"

```

### Form-level Error Messaging

It is sometimes useful to display error messages in a different area isntead
of underneath the `TextField`. Enable the `disableMessage` option and manually
render the `errorMessage` instead.

> !Info! See the [W3C User Notifications](https://www.w3.org/WAI/tutorials/forms/notifications/)
> for more information on creating accessible form-level alerts.

```demo source="./FormLevelErrorMessagesExample.tsx"

```

## Parameters

- `options` - An object with the following definition:

````ts disableTransform
export type TextFieldValidationOptions = Pick<
  InputHTMLAttributes<HTMLInputElement>,
  "minLength" | "maxLength" | "required" | "pattern"
>;

export type TextFieldChangeHandlers<
  E extends HTMLInputElement | HTMLTextAreaElement,
> = Pick<HTMLAttributes<E>, "onBlur" | "onChange" | "onInvalid">;

export interface TextFieldHookOptions<
  E extends HTMLInputElement | HTMLTextAreaElement,
>
  extends TextFieldValidationOptions, TextFieldChangeHandlers<E> {
  /**
   * An optional id to use for the `TextField` or `TextArea` that is also used
   * to create an id for the inline help/error messages.
   *
   * @defaultValue `"text-field-" + useId()`
   */
  id?: string;

  /**
   * An optional ref that should be merged with the ref returned by this hook.
   * This should really only be used if you are making a custom component using
   * this hook and forwarding refs. If you need a ref to access the `<input>` or
   * `<textarea>` DOM node, you can use the `fieldRef` returned by this hook
   * instead.
   *
   * @example Accessing TextField DOM Node
   * ```tsx
   * import { TextField, useTextField } from "@react-md/core";
   * import { useEffect } from "react";
   * import type { ReactElement } from "react";
   *
   * function Example(): ReactElement {
   *   const { fieldRef, fieldProps } = useTextField({ name: "example" });
   *
   *   useEffect(() => {
   *     fieldRef.current;
   *     //       ^ HTMLInputElement | null
   *   }, [fieldRef]);
   *
   *   return <TextField {...fieldProps} label="Example" />;
   * }
   * ```
   */
  ref?: Ref<E>;

  /**
   * A unique name to attach to the `TextField`, `TextArea` or `Password`
   * component.
   */
  name: string;

  /**
   * Boolean if the `FormMessage` should also display a counter for the
   * remaining letters allowed based on the `maxLength`.
   *
   * This will still be considered false if the `maxLength` value is not
   * provided.
   *
   * @defaultValue `false`
   */
  counter?: boolean;

  /**
   * This is used internally for the `useNumberField` hook and probably
   * shouldn't be used otherwise. This is just passed into the
   * {@link getErrorMessage} options and is used for additional validation.
   *
   * @defaultValue `false`
   */
  isNumber?: boolean;

  /**
   * The default value to use for the `TextField` or `TextArea` one initial
   * render. If you want to manually change the value to something else after
   * the initial render, either change the `key` for the component containing
   * this hook, or use the `setState` function returned from this hook.
   *
   * @defaultValue `""`
   */
  defaultValue?: UseStateInitializer<string>;

  /**
   * An optional help text to display in the `FormMessage` component when there
   * is not an error.
   */
  helpText?: ReactNode;

  /**
   * A function used to determine if the `TextField` or `TextArea` is an in
   * errored state.
   *
   * @see {@link defaultIsErrored}
   * @defaultValue `defaultIsErrored`
   */
  isErrored?: IsErrored;

  /**
   * An optional error icon used in the {@link getErrorIcon} option.
   *
   * @defaultValue `getIcon("error")`
   */
  errorIcon?: ReactNode;

  /**
   * A function used to get the error icon to display at the right of the
   * `TextField` or `TextArea`. The default behavior will only show an icon when
   * the `error` state is `true` and an `errorIcon` option has been provided.
   *
   * @see {@link defaultGetErrorIcon}
   * @defaultValue `defaultGetErrorIcon`
   */
  getErrorIcon?: GetErrorIcon;

  /**
   * A function to get and display an error message based on the `TextField` or
   * `TextArea` validity.
   *
   * @see {@link defaultGetErrorMessage}
   * @defaultValue `defaultGetErrorMessage`
   */
  getErrorMessage?: GetErrorMessage;

  /**
   * An optional function that will be called whenever the `error` state is
   * changed. This can be used for more complex forms to `disable` the Submit
   * button or anything else if any field has an error.
   *
   * @defaultValue `() => {}`
   */
  onErrorChange?: ErrorChangeHandler<E>;

  /**
   * Boolean if the `TextField` or `TextArea` will **not** be rendered along
   * with a `FormMessage` component. This will prevent the `aria-describedby`
   * prop from being returned when set to `true`.
   *
   * @defaultValue `false`
   */
  disableMessage?: boolean;

  /**
   * Boolean if the `maxLength` prop should not be passed to the `TextField`
   * component since it will prevent any additional characters from being
   * entered in the text field which might feel like weird behavior to some
   * users. This should really only be used when the `counter` option is also
   * enabled and rendering along with a `FormMessage` component.
   *
   * @defaultValue `false`
   */
  disableMaxLength?: boolean;

  /**
   * @defaultValue `"recommended"`
   */
  validationType?: TextFieldValidationType;
}
````

## Returns

The return type has the following shape, but changes depending on the provided options.
Just know that it is always save to pass the `fieldProps` to the `TextField` component.

```ts disableTransform
export interface TextFieldHookState {
  /**
   * The current value for the `TextField` or `TextArea`.
   */
  value: string;

  /**
   * This will be `true` when the `TextField`/`TextArea` has an error.
   */
  error: boolean;

  /**
   * The error message returned by {@link GetErrorMessage}/the browser's
   * validation message. This is normally an empty string when the {@link error}
   * state is `false`.
   */
  errorMessage: string;
}

export interface TextFieldImplementation<
  E extends HTMLInputElement | HTMLTextAreaElement,
> extends TextFieldHookState {
  fieldRef: RefObject<E>;
  reset: () => void;
  setState: UseStateSetter<Readonly<TextFieldHookState>>;
  fieldProps: ProvidedTextFieldProps<E>;
}

export interface ProvidedTextFieldProps<
  E extends HTMLInputElement | HTMLTextAreaElement,
>
  extends
    TextFieldValidationOptions,
    TextFieldChangeHandlers<E>,
    Required<Pick<TextFieldProps, "id" | "name" | "value" | "error">>,
    Pick<TextFieldProps, "aria-describedby" | "rightAddon"> {
  /**
   * A ref that must be passed to the `TextField`/`TextArea` so that the custom
   * validity behavior can work.
   */
  ref: RefCallback<E>;
}
```

## See Also

- [W3C Forms](https://www.w3.org/WAI/tutorials/forms/)
- [W3C User Notifications](https://www.w3.org/WAI/tutorials/forms/notifications/)
- [useNumberField](./use-number-field)
